import json
import random
from pathlib import Path
from dataclasses import dataclass
from typing import NamedTuple, Dict, Literal, Tuple, cast

# 定义 PunchProfile 类
class PunchProfile(NamedTuple):
    pre_msg: str
    hit_msg: str
    blocked_msg: str
    choices: int
    threshold: int
    hit_damage: int
    block_damage: int
    knockout_possible: bool = False
    heal_amount: int = 0  # 默认没有恢复能力

    def is_hit(self):
        return random.randint(1, self.choices) <= self.threshold

# 定义 Player 类
@dataclass
class Player:
    name: str
    best: int
    weakness: int
    is_computer: bool
    punch_profiles: Dict[Literal[1, 2, 3, 4, 5], PunchProfile]
    damage: int = 0
    score: int = 0
    knockedout: bool = False
    health: int = 20
    heal_used: bool = False

    def get_punch_choice(self) -> Literal[1, 2, 3, 4, 5]:
        if self.is_computer:
            return random.randint(1, 5)
        while True:
            try:
                punch = int(input(f"{self.name}的招式是？"))
                if 1 <= punch <= 5:
                    return punch
                else:
                    print("招式必须是1到5之间的数字，请重新输入。")
            except ValueError:
                print("请输入一个有效的数字。")

    def use_heal(self, heal_amount: int):
        if not self.heal_used:
            self.health += heal_amount
            print(f"{self.name}使用了恢复技能，恢复了{heal_amount}点血量。")
            self.heal_used = True
            if self.health > 20:
                self.health = 20
        else:
            print(f"{self.name}已经使用过恢复技能了。")
# 击倒阈值
KNOCKOUT_THRESHOLD = 35
# 击晕信息
KNOCKOUT_COLD = "{loser}被击晕了无法继续进行比赛，胜利属于{winner}"

# 获取选手的弱点信息
def get_vulnerability():
    print("他的弱点是？")
    while True:
        try:
            weakness = int(input())
            if 1 <= weakness <= 4:
                return weakness
            else:
                print("弱点必须是1到4之间的数字，请重新输入。")
        except ValueError:
            print("请输入一个有效的数字。")

# 获取电脑的弱点信息
def get_opponent_stats() -> Tuple[int, int]:
    opponent_best = 0
    opponent_weakness = 0
    while opponent_best == opponent_weakness:
        opponent_best = random.randint(1, 4)
        opponent_weakness = random.randint(1, 4)
    return opponent_best, opponent_weakness

# 获取招式的基本信息
def read_punch_profiles(filepath: Path):
    with open(filepath, encoding='utf-8') as f:
        punch_profiles_dict = json.load(f)
    return {
        cast(Literal[1, 2, 3, 4, 5], int(key)): PunchProfile(**value)
        for key, value in punch_profiles_dict.items()
    }

# 定义 main 函数
def main() -> None:
    print("拳击游戏")
    print("design by czq")
    print("由czq设计创造")
    print("202312060304")
    print("这个游戏采取奥运规则，三局两胜")

    print("你的对手的名字是？")
    opponent_name = input()

    print("你的名字是？")
    player_name = input()

    print("不同的出拳策略 1 摆拳 2 平勾拳 3上钩拳 4 刺拳 5 恢复技能")
    print("你擅长的招式是？")
    player_best = int(input())
    player_weakness = get_vulnerability()
    player = Player(
        name=player_name,
        best=player_best,
        weakness=player_weakness,
        is_computer=False,
        punch_profiles=read_punch_profiles(Path(__file__).parent / "player-profile.json"),
    )

    opponent_best, opponent_weakness = get_opponent_stats()
    opponent = Player(
        name=opponent_name,
        best=opponent_best,
        weakness=opponent_weakness,
        is_computer=True,
        punch_profiles=read_punch_profiles(Path(__file__).parent / "opponent-profile.json"),
    )

    for round_number in range(1, 4):  # Ensure three rounds are played
        if player.knockedout or opponent.knockedout:
            break
        play_round(round_number, player, opponent)

    if player.knockedout:
        print(KNOCKOUT_COLD.format(loser=player.name, winner=opponent.name))
    elif opponent.knockedout:
        print(KNOCKOUT_COLD.format(loser=opponent.name, winner=player.name))
    elif opponent.score > player.score:
        print(f"{opponent.name}打败了{player.name}")
    else:
        print(f"{player.name}打败了{opponent.name}")

    print("\n\n比赛结束")
    print("感谢游玩")

# 定义 is_opponents_turn 函数
def is_opponents_turn() -> bool:
    return random.randint(1, 10) > 5

# 定义 play_round 函数
# 定义 play_round 函数
def play_round(round_number: int, player: Player, opponent: Player) -> None:
    print(f"第{round_number}轮次。\n开始....\n")
    if opponent.score >= 2 or player.score >= 2:
        return

    for _action in range(7):  # 假设每轮有7次行动机会
        if is_opponents_turn():
            punch = opponent.get_punch_choice()
            active = opponent
            passive = player
        else:
            punch = player.get_punch_choice()
            active = player
            passive = opponent

        punch_profile = active.punch_profiles[punch]

        if punch == active.best:
            active.damage += 2

        if punch == 5:  # 恢复技能
            active.use_heal(punch_profile.heal_amount)
            continue

        print(punch_profile.pre_msg.format(opponent=opponent.name, player=player.name))

        if passive.weakness == punch or punch_profile.is_hit():
            print(punch_profile.hit_msg.format(opponent=opponent.name, player=player.name, hit_damage=punch_profile.hit_damage))
            passive.health -= punch_profile.hit_damage
            if punch_profile.knockout_possible and active.damage > KNOCKOUT_THRESHOLD:
                if active is opponent:
                    player.knockedout = True
                else:
                    opponent.knockedout = True
                # 检查是否有玩家被击倒
                if player.knockedout or opponent.knockedout:
                    break  # 使用 break 退出循环
        else:
            print(punch_profile.blocked_msg.format(opponent=opponent.name, player=player.name, hit_damage=punch_profile.block_damage))
            passive.health -= punch_profile.block_damage

        if passive.health <= 0:
            passive.knockedout = True
            break  # 使用 break 退出循环

        # 打印当前回合的血量情况
        print(f"{active.name}的攻击造成了{punch_profile.hit_damage}点伤害，{passive.name}剩余血量：{passive.health}")
        print(f"{passive.name}的攻击造成了{punch_profile.block_damage}点伤害，{active.name}剩余血量：{active.health}")

    if player.knockedout:
        print(KNOCKOUT_COLD.format(loser=player.name, winner=opponent.name))
    elif opponent.knockedout:
        print(KNOCKOUT_COLD.format(loser=opponent.name, winner=player.name))
    else:
        if player.health > opponent.health:
            print(f"{player.name}获得了第{round_number}场胜利")
            player.score += 1
        else:
            print(f"{opponent.name}获得了第{round_number}场胜利")
            opponent.score += 1



# 确保 main 函数在代码的最后被调用
if __name__ == "__main__":
    main()